package com.yuan.util.verify;

import com.yuan.util.number.RandomUtil;
import com.yuan.util.string.StrUtil;

import java.util.Calendar;
import java.util.Date;

/**
 * Explain:     [校验工具类]
 * Date:        [2017/8/3 09:45]
 * Coder:       [YouYuan]
 * Version:     [1.0]
 */
public class VerifyUtil {

    private static final int[] IDCARD_WI = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};//身份证每一位的加权因子
    private static final char[] IDCARD_CHECK_SEQUENCE_NUMS = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};//身份证最后一位校验码序列
    private static final String IDCARD_REGEX = "^(^\\d{15}$|^\\d{18}$|^\\d{17}(\\d|X|x))$";//身份证校验正则

    /**
     * 校验身份证号,返回该身份证是否合法,算法使用正则+日期+身份证校验码算法组合验证
     *
     * @param idCard
     * @return
     */
    public static boolean checkIdCard(String idCard) {
        if (idCard == null || idCard.trim().length() == 0) {
            return false;
        }
        idCard = idCard.trim();
        if (idCard.matches(IDCARD_REGEX)) {
            if (idCard.length() == 15) {
                try {
                    Date.parse(idCard.substring(6, 8) + "/" + idCard.substring(8, 10) + "/" + idCard.substring(10, 12));
                } catch (Exception e) {
                    return false;
                }
                return true;
            } else {
                try {
                    Date.parse(idCard.substring(6, 10) + "/" + idCard.substring(10, 12) + "/" + idCard.substring(12, 14));
                } catch (Exception e) {
                    return false;
                }
                return calculateCheckChar(idCard) == (idCard.charAt(idCard.length() - 1));
            }
        }
        return false;
    }

    /**
     * 计算身份证的验证位
     * @param idCard
     * @return
     */
    private static char calculateCheckChar(String idCard) {
        if (idCard == null || idCard.length() < 17) {
            return '!';
        }
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            char t = idCard.charAt(i);
            int num = t - '0';
            sum += (num * IDCARD_WI[i]);
        }
        sum %= 11;
        return IDCARD_CHECK_SEQUENCE_NUMS[sum];
    }

    /**
     * 生成一个身份证
     * @return
     */
    public static String generatorIdCard() {
        StringBuilder idCard = new StringBuilder();
        idCard.append(RandomUtil.nextInt(110000, 800000));
        idCard.append(randomBirthday());
        idCard.append(RandomUtil.nextInt(100, 999));
        idCard.append(calculateCheckChar(idCard.toString()));
        return idCard.toString();
    }

    private static final char[] TEMP_IDCARD_ARR = new char[18];

    /**
     * 根据给定格式生成合规的身份证，需要替换的值用#代替，例如##4000198001014513
     * @param format
     * @return
     */
    public static String generatorIdCard(String format) {
        format = StrUtil.trim(format);
        int length = format.length();
        if (StrUtil.isEmpty(format) || length != 18) {
            return generatorIdCard();
        }
        String tempIdCard = generatorIdCard();
        StringBuilder idCard = new StringBuilder();
        int index = 0;
        final int[] IDCARD_FORMATE_INDEX_ARR = new int[18];
        for (int i = 0; i < length; i++) {
            char c = format.charAt(i);
            if ((c >= '0' && c <= '9') || (c == 'x' || c == 'X')) {
                TEMP_IDCARD_ARR[i] = c;
            } else {
                TEMP_IDCARD_ARR[i] = tempIdCard.charAt(i);
                IDCARD_FORMATE_INDEX_ARR[index++] = i;
            }
        }
        idCard.append(TEMP_IDCARD_ARR);
        int p = 0;
        for (int k = 0; k < IDCARD_FORMATE_INDEX_ARR.length; k++) {
            for (int i = 0; i < 10; i++) {
                if (!checkIdCard(idCard.toString())) {
                    if (i == 0 && IDCARD_FORMATE_INDEX_ARR[p] == 0) {
                        continue;// 第一位不能为0
                    }
                    TEMP_IDCARD_ARR[IDCARD_FORMATE_INDEX_ARR[p]] = (char) (i + '0');
                } else {
                    break;
                }
                idCard.setLength(0);
                idCard.append(TEMP_IDCARD_ARR);
            }
            if (!checkIdCard(idCard.toString())) {
                p++;
            } else {
                break;
            }
        }
        return idCard.toString();
    }

    /**
     * 随机生成生日
     * @return
     */
    public static String randomBirthday() {
        Calendar birthday = Calendar.getInstance();
        birthday.set(Calendar.YEAR, (int)(RandomUtil.nextFloat() * 60) + 1950);
        birthday.set(Calendar.MONTH, (int) (RandomUtil.nextFloat() * 12));
        birthday.set(Calendar.DATE, (int) (RandomUtil.nextFloat() * 31));
        StringBuilder builder = new StringBuilder();
        builder.append(birthday.get(Calendar.YEAR));
        long month = birthday.get(Calendar.MONTH) + 1;
        if (month < 10) {
            builder.append("0");
        }
        builder.append(month);
        long date = birthday.get(Calendar.DATE);
        if (date < 10) {
            builder.append("0");
        }
        builder.append(date);
        return builder.toString();
    }
}
